/*
// 说明：xinterface 组件旨在替换虚函数，简化 GC 结构
// 用法：如下

#define xuser mixc::powerful_cat
#include"io/tty.hpp"
#include"macro/xinterface.hpp"
#include"mixc.hpp"

namespace xuser{
    xinterface(
        xname(isay_hello),
        xfunc(say_hello_to, void(asciis some_one)) // <- 没有多余的逗号
    ) $

    struct cat{
        void say_hello_to(asciis some_one){
            tty.write_line("hello! \v this is Cat speaking!", some_one);
        }
    };

    void hello(isay_hello const & me){
        me->say_hello_to("leon");
    }

    xinit(the_main){
        {
            // 正确
            cat         the_cat;
            isay_hello  ish = the_cat;
            ish->say_hello_to("keyti");

            // 正确
            hello(the_cat);

            // 正确
            hello(cat{});
        }

        {
            // 错误 ========================================================
            // isay_hello 接口需要存活的实例（cat）
            // 而 cat 在赋值给 isay_hello 对象 ish 后就析构了
            // 虽然对于无成员变量的 cat 来说，这样并不会产生错误的输出，
            // 但我们建议不要这么做
            isay_hello ish = cat();
            ish->say_hello_to("System");
        }
    };



    xinterface(
        xname(isum),
        xfunc(sum, 
            uxx(uxx a, uxx b),
            uxx(uxx a, uxx b, uxx c)    // 支持重载
        ) // <- 没有多余的逗号
    ) $

    struct ax{
        uxx sum(uxx a0, uxx a1){
            return a0 + a1;
        }

        uxx sum(uxx a0, uxx a1, uxx a2){
            return a0 + a1 + a2;
        }
    };

    void sum(isum callback){
        xhint(callback->sum(1, 2));
        xhint(callback->sum(1, 2, 3));
    }

    xinit(the_main){
        sum(ax{});
    };



    xinterface(
        xname(iweak),
        xfunc(the_weak_match,
            // 支持弱匹配，如果 iweak::the_weak_match 的参数可以传递给实现类，
            // 且返回值可以接受实现类的返回值，那么就可以匹配成功
            uxx(uxx value)
        )
    ) $

    struct weak_u08{
        // iweak::the_weak_match 期望
        // uxx the_weak_match(uxx value); 类型的成员函数，但由于参数和返回值是兼容的，所以支持隐式转换
        u08 the_weak_match(u08 value){
            return value;
        }
    };

    struct weak_u16{
        u16 the_weak_match(u16 value){
            return value;
        }
    };

    void test_weak(iweak const & callback){
        xhint(callback->the_weak_match(10));
    }

    xinit(the_main){
        test_weak(weak_u08{});
        test_weak(weak_u16{});
    };
}

*/

#ifndef xpack_macro_xinterface
#define xpack_macro_xinterface
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::macro_xinterface::inc
#include"macro/private/word.hpp"
#include"macro/private/xlist.hpp"
#include"macro/xstruct.hpp" // for macro $
#include"macro/xmodify.hpp"
#include"macro/xnew.hpp"
#include"meta/has_constructor.hpp"
#include"meta/is_class.hpp"
#include"meta/is_same.hpp"
#include"meta_seq/tlist.hpp"
#pragma pop_macro("xuser")

namespace mixc::macro_xinterface{
    template<class object_t, uxx length_v>
    inline voidp s_func_table[length_v];

    struct dummy{ enum { __func_length }; };

    template<class func_list_t>
    struct this_call_pair{
        voidp   this_ptr    = nullptr;
        voidp * func_table  = nullptr;

        template<class object_t>
        constexpr this_call_pair(object_t const & this_ref) : 
            this_ptr(xmodify(this_ref)), 
            func_table(s_func_table<object_t, func_list_t::__func_length>){
        }

        constexpr this_call_pair(){};
    };

    using this_call_pairp =  this_call_pair<dummy> *;

    template<
        template<uxx, class ...> class  docker_t, 
        uxx                             i, 
        class                           ret,
        class ...                       args_t,
        class ...                       old_overloadx,
        class ...                       new_overloadx
    >
    inline auto make_flat(inc::tlist<new_overloadx...>, ret(*)(args_t...), old_overloadx...){
        using new_list = inc::tlist<
            new_overloadx...,
            docker_t<i, ret, args_t...>
        >;

        if constexpr (sizeof...(old_overloadx) == 0){
            return new_list{};
        }
        else{
            return make_flat<docker_t, i + 1>(new_list{}, (old_overloadx)nullptr...);
        }
    }

    template<
        template<class ...> class       docker_t,
        class ...                       overloads_t
    >
    inline auto docker_specialize(inc::tlist<overloads_t...>){
        return docker_t<overloads_t...>{};
    }

    template<uxx i, template<uxx> class ... func>
    struct functional_assembly{
        template<class object_t>
        constexpr functional_assembly(object_t const &){}
        constexpr functional_assembly(){}
    private:
        template<class> friend struct this_call_pair;
        enum { __func_length = i };
    };

    template<
        uxx                             i,
        template<uxx> class             func, 
        template<uxx> class         ... funcx
    >
    struct functional_assembly<i, func, funcx...> : 
        func<i>, 
        functional_assembly<i + func<i>::__overload_list::length, funcx...>{

        using base_t = functional_assembly<i + func<i>::__overload_list::length, funcx...>;

        template<class object_t>
        requires(
            inc::has_constructor<func<i>, void(object_t)>
        )
        constexpr functional_assembly(object_t const & this_ref) :
            func<i>(this_ref), base_t(this_ref){
        }
        constexpr functional_assembly(){}
    };

    template<
        template<uxx> class ...         funcx,
        template<uxx> class ...         func_next,
        class ...                       fax
    >
    inline auto make_assembly(
        functional_assembly<0, funcx...>, 
        functional_assembly<0, func_next...>, 
        fax ... list){

        using new_fa = functional_assembly<0, funcx..., func_next...>;

        if constexpr (sizeof...(fax) == 0){
            return new_fa{};
        }
        else{
            return make_assembly(new_fa{}, list...);
        }
    }

    template<class fa, class ... fax>
    using functional_assemblyx      = decltype(
        make_assembly(
            functional_assembly<0>{}, 
            fax{}...,
            fa{}
        )
    );

    template<
        template<uxx, class ...> class  func_docker,
        uxx                             i,
        class                       ... overloads_t
    >
    using overload_list = decltype(
        make_flat<func_docker, i>(inc::tlist<>{}, (overloads_t *)nullptr...)
    );

    template<
        template<class ...> class       docker_t,
        class                           overload_list
    >
    using specialized_docker = decltype(
        docker_specialize<docker_t>(overload_list{})
    );

    template<class target, class constructor>
    concept __itf_hc    = inc::has_constructor<target, constructor>;

    template<class ... type>
    using __itf_tl      = inc::tlist<type...>;
};

template<class target, class constructor>
concept __itf_hc = mixc::macro_xinterface::__itf_hc<target, constructor>;

// 需要排除非类类型，编译器暂时不支持 xinterface 中 requires 格式的非类类型排除
template<class type>
concept __itf_ic = mixc::macro_xinterface::inc::is_class<type>;

template<class type_a, class type_b>
concept __itf_is_same = mixc::macro_xinterface::inc::is_same<type_a, type_b>;

template<class inject_test>
concept __itf_test = requires(inject_test object){
    object.test();
};


template<class __func_list>
using __itf_tcp = mixc::macro_xinterface::this_call_pair<__func_list>;

using __itf_tcpp = mixc::macro_xinterface::this_call_pairp;

template<class ... type>
using __itf_tl = mixc::macro_xinterface::__itf_tl<type...>;

template<
    template<uxx, class ...> class  func_docker,
    uxx                             i,
    class ...                       overloads_t
>
using __itf_ol = mixc::macro_xinterface::overload_list<func_docker, i, overloads_t...>;

template<
    template<class ...> class       docker_t,
    class                           overload_list
>
using __itf_sd = mixc::macro_xinterface::specialized_docker<docker_t, overload_list>;

template<
    uxx                             i, 
    template<uxx> class         ... func
>
using __itf_fa = mixc::macro_xinterface::functional_assembly<i, func...>;

template<class fa, class ... fax>
using __itf_fax = mixc::macro_xinterface::functional_assemblyx<
    // fa::__func_list 会在 functional_assemblyx 中调整到末尾位置以符合继承结构的内存布局
    typename fa::__func_list,
    typename fax::__func_listx...
>;

#define __xitf_xthe__
#define __xitf_xthe_name__(...)                 NAME
#define __xitf_xthe_tmpl__(...)                 NAME<__VA_ARGS__>
#define __xitf_xthe_spec__(...)                 NAME<__VA_ARGS__>
#define __xitf_xthe_pubb__(...)
#define __xitf_xthe_func__(...)
#define __xitf_xthe_attr__(...)
#define __xitf_xthe_oper__(...)


#define __xitf_name__
#define __xitf_name_name__(NAME)                NAME
#define __xitf_name_tmpl__(NAME,...)            NAME
#define __xitf_name_spec__(NAME,...)            NAME
#define __xitf_name_pubb__(...)
#define __xitf_name_func__(...)
#define __xitf_name_attr__(...)
#define __xitf_name_oper__(...)

#define __xitf_namex__
#define __xitf_namex_name__(NAME)               NAME
#define __xitf_namex_tmpl__(NAME,...)           NAME
#define __xitf_namex_spec__(NAME,...)           NAME<__VA_ARGS__>
#define __xitf_namex_pubb__(...)
#define __xitf_namex_func__(...)
#define __xitf_namex_attr__(...)
#define __xitf_namex_oper__(...)

#define __xitf_pubb__
#define __xitf_pubb_name__(...)
#define __xitf_pubb_tmpl__(...)
#define __xitf_pubb_spec__(...)
#define __xitf_pubb_pubb__(...)                 , __VA_ARGS__
#define __xitf_pubb_func__(...)
#define __xitf_pubb_attr__(...)
#define __xitf_pubb_oper__(...)

#define __xitf_decl_func__
#define __xitf_decl_func_name__(NAME,...)       using the_t = NAME;
#define __xitf_decl_func_tmpl__(NAME,...)       using the_t = NAME<__VA_ARGS__>;
#define __xitf_decl_func_spec__(NAME,...)       using the_t = NAME<__VA_ARGS__>;
#define __xitf_decl_func_pubb__(...)
#define __xitf_decl_func_func__(NAME,...)       __xfunc_helper__(,NAME,__VA_ARGS__)
#define __xitf_decl_func_attr__(NAME,...)       __xfunc_helper__(*,NAME,__VA_ARGS__)
#define __xfunc_helper__(IS_PROP,NAME,...)                                              \
    template<uxx __i_v, class __ret_t, class ... __args_t>                              \
    struct __lv0_ ## NAME{                                                              \
    private:                                                                            \
        template<class __object_t>                                                      \
        struct __shell{                                                                 \
            static auto test(){                                                         \
                struct __closure{                                                       \
                    static __ret_t __shell(                                             \
                        __object_t * __this_ptr, __args_t ... __list                    \
                    ){                                                                  \
                        return (IS_PROP __this_ptr)->NAME(__list...);                   \
                    }                                                                   \
                };                                                                      \
                return & __closure::__shell;                                            \
            }                                                                           \
        };                                                                              \
    public:                                                                             \
        constexpr __lv0_ ## NAME(){}                                                    \
                                                                                        \
        template<__itf_ic __object_t>                                                   \
        requires(__itf_test<__shell<__object_t>>)                                       \
        constexpr __lv0_ ## NAME(__object_t const &){                                   \
            __itf_tcpp(this)->func_table[__i_v] = voidp(__shell<__object_t>::test());   \
        }                                                                               \
                                                                                        \
        __ret_t NAME(__args_t ... __list) const {                                       \
            __itf_tcpp __p  = __itf_tcpp(this);                                         \
            using __f       = __ret_t(*)(voidp, __args_t...);                           \
            return __f(__p->func_table[__i_v])(__p->this_ptr, __list...);               \
        }                                                                               \
    };                                                                                  \
                                                                                        \
    template<class ... __overload>                                                      \
    struct __lv1_ ## NAME : __overload...{                                              \
        template<class __object_t>                                                      \
        requires(... and __itf_hc<__overload, void(__object_t)>)                        \
        __lv1_ ## NAME(__object_t const & this_ref) :                                   \
            __overload(this_ref)...{                                                    \
        }                                                                               \
        __lv1_ ## NAME(){}                                                              \
                                                                                        \
        using __overload::NAME...;                                                      \
        using __overload_list = __itf_tl<__overload...>;                                \
    };                                                                                  \
                                                                                        \
    template<uxx __i_v> using __ ## NAME = __itf_sd<                                    \
        __lv1_ ## NAME, __itf_ol<                                                       \
            __lv0_ ## NAME, __i_v, __VA_ARGS__                                          \
        >                                                                               \
    >;

#define __xitf_decl_func_oper__(...)

#define __xitf_layout_func__
#define __xitf_layout_func_name__(...)
#define __xitf_layout_func_tmpl__(...)
#define __xitf_layout_func_spec__(...)
#define __xitf_layout_func_pubb__(...)
#define __xitf_layout_func_func__(NAME,...)  , __ ## NAME
#define __xitf_layout_func_attr__(NAME,...)  , __ ## NAME
#define __xitf_layout_func_oper__(...)

#define xinterface(...)                                                                 \
struct __xlist__(__xitf_namex_, __VA_ARGS__) {                                          \
    __xlist__(__xitf_decl_func_, __VA_ARGS__)                                           \
    using __func_list  = __itf_fa<0 __xlist__(__xitf_layout_func_, __VA_ARGS__)>;       \
    using __func_listx = __itf_fax<the_t __xlist__(__xitf_pubb_,__VA_ARGS__)>;          \
                                                                                        \
    template<class __object_t>                                                          \
    requires(                                                                           \
        not __itf_is_same<the_t, __object_t> /*需要排前面*/                             \
        and __itf_hc<__func_listx, void(__object_t)>)                                   \
    constexpr __xlist__(__xitf_name_, __VA_ARGS__)(__object_t const & __this_ref) :     \
        __pair(__this_ref){                                                             \
                                                                                        \
        if (__pair.func_table[0] == nullptr){                                           \
            xnew (this) __func_listx(__this_ref);                                       \
        }                                                                               \
    }                                                                                   \
                                                                                        \
    constexpr __xlist__(__xitf_name_, __VA_ARGS__)(){}                                  \
                                                                                        \
    __func_listx const * operator-> () const {                                          \
        return (__func_listx *)this;                                                    \
    }                                                                                   \
private:                                                                                \
    __itf_tcp<__func_listx> __pair;                                                     \

#endif
